//: C16:IStack.cpp
// From Thinking in C++, 2nd Edition
// Available at http://www.BruceEckel.com
// (c) Bruce Eckel 1999
// Copyright notice in Copyright.txt
// Simple integer stack
#include "../require.h"
#include <iostream>
using namespace std;

class IStack
{
    static const int ssize = 100;
    int stack[ssize];
    int top;
public:
    IStack() : top(0) {
        stack[top] = 0;
    }
    void push(int i) {
        if (top < ssize) stack[top++] = i;
    }
    int pop() {
        return stack[top > 0 ? --top : top];
    }
    friend class IStackIter;
};

// An iterator is a "super-pointer":
class IStackIter
{
    IStack& S;
    int index;
public:
    IStackIter(IStack& is)
            : S(is), index(0) {}
    int operator++() { // Prefix form
        if (index < S.top - 1) index++;
        return S.stack[index];
    }
    int operator++(int) { // Postfix form
        int returnval = S.stack[index];
        if (index < S.top - 1) index++;
        return returnval;
    }
};
// For interest, generate Fibonacci numbers:
int fibonacci(int n)
{
    const int sz = 100;
    require(n < sz);
    static int f[sz]; // Initialized to zero
    f[0] = f[1] = 1;
    // Scan for unfilled array elements:
    int i;
    for (i = 0; i < sz; i++)
        if (f[i] == 0) break;
    while (i <= n) {
        f[i] = f[i-1] + f[i-2];
        i++;
    }
    return f[n];
}

int main()
{
    IStack is;
    for (int i = 0; i < 20; i++)
        is.push(fibonacci(i));
    // Traverse with an iterator:
    IStackIter it(is);
    for (int j = 0; j < 20; j++)
        cout << it++ << endl;
    for (int k = 0; k < 20; k++)
        cout << is.pop() << endl;
} ///:~
